package vip.minesweeper.model;

import java.util.Random;

import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;

/**
 * Class representing Mine Suite.
 * 
 * @author Vladimir Tsanev
 * 
 */
public class MinesSuite {

	private Square[][] squares;

	/**
	 * Crates new MinesSuite by specified rows, columns, and number of mines.
	 * 
	 * @param rows
	 * @param columns
	 * @param numberOfMines
	 * @throws IllegalArgumentException
	 *             if rows, columns or number of mines are less than or equal to
	 *             zero. And if numberOfMines are more than rows*columns
	 */
	public MinesSuite(int rows, int columns, int numberOfMines) {
		validateParameters(rows, columns, numberOfMines);
		this.squares = new Square[rows][columns];
		// First we fill the mines;
		// TODO implement squares initialization methods using the randomizer.
		this.fillMines(numberOfMines);
		this.calculateFreeMinesNumber();
	}

	private void validateParameters(int rows, int columns, int numberOfMines) {
		if (rows <= 0) {
			throw new IllegalArgumentException("rows cannot be less than one");
		}
		if (columns <= 0) {
			throw new IllegalArgumentException(
					"columns cannot be less than one");
		}
		if (numberOfMines <= 0) {
			throw new IllegalArgumentException(
					"number of mines cannot be less than one");
		}
		if (numberOfMines > rows * columns) {
			throw new IllegalArgumentException(
					"number of mines cannot be more than rows*columns");
		}
	}

	private void calculateFreeMinesNumber() {
		for(int i = 0; i < squares.length; i++){
			for(int k = 0; k < squares[i].length; k++){
				if (! (squares[i][k] instanceof MineSquare)){
					//FIXME change listener parameter null
					squares[i][k] = new FreeSquare(null, numberOfMinesAround(i, k));
				}
			}
		}

	}
	
	private int mine(int row, int coloumn){
		if(row < 0 || coloumn < 0 || row > squares.length || coloumn > squares[0].length){
			return 0;
		}
		if(squares[row][coloumn] instanceof MineSquare){
			return 1;
		}
		return 0;
	}
	
	private int numberOfMinesAround(int row, int coloumn){
		int numberOfMinesAround = 0;
		numberOfMinesAround = mine(row - 1, coloumn - 1) + 
							  mine(row - 1, coloumn) +
							  mine(row - 1, coloumn + 1) +
							  mine(row, coloumn - 1) +
							  mine(row, coloumn + 1) +
							  mine(row + 1, coloumn - 1) +
							  mine(row + 1, coloumn) +
							  mine(row + 1, coloumn + 1);	
		return numberOfMinesAround;
	}

	private void fillMines(int numberOfMines) {
		Random randomizer = new Random(System.currentTimeMillis());
		int lengthSquare = this.squares.length;
		int widthSquare = this.squares[0].length;
		int currentRow = 0;
		int currentColoumn = 0;
		for(int counterMines = numberOfMines; counterMines > 0; counterMines--){
			currentRow = randomizer.nextInt(lengthSquare);
			currentColoumn = randomizer.nextInt(widthSquare);
			if(squares[currentRow][currentColoumn] == null){
				//FIXME change listener parameter null
				squares[currentRow][currentColoumn] = new MineSquare(null);
			}
		}
	}

	/**
	 * Returns {@link Square} object for specified row and columns.
	 * 
	 * @param row
	 *            row of the square
	 * @param column
	 *            column of the square
	 * @return the square on the given row and column.
	 * @throws IllegalArgumentException
	 *             if row and column are not valid parameters.
	 */
	public Square getSquareAt(int row, int column) {
		// TODO add validation for row and column.
		return this.squares[row][column];
	}

	public void openSquareAt(int row, int column) {
		// TODO add validation for row and column.
		this.squares[row][column].open();
	}
}
